<!--
 * @Author: zi.yang
 * @Date: 2021-03-11 21:03:56
 * @LastEditors: zi.yang
 * @Description: 搜索栏 组件
 * @FilePath: \vue-music\src\components\search\music-search.vue
-->
<template>
  <div class="search-input">
    <i class="iconfont iconsearch"></i>
    <input
      type="text"
      placeholder="搜索歌曲"
      v-model.trim="userInput"
      @keyup.enter="handleKeyDown(userInput)"
      @input="handleToSuggest(userInput)"
    />
    <i class="iconfont iconclose" @click="handleClickBack()"></i>
  </div>
</template>

<script lang="ts">
/* global Readonly:false */
import axios from 'axios';
import {
  reactive, toRefs, watch,
} from '@vue/composition-api';
// @ts-ignore
import Storage from '../common/storage.ts';
// @ts-ignore

const storage = new Storage();
// 历史记录存储
function HistorayStorage(userInput: string): void {
  // 每次都从 localStorage 中读取数据
  let searchHistory: Array<string> = [];
  storage.getItem({
    key: 'searchHistory',
    success: (data:Array<string>) => {
      if (data === null) {
        return;
      }
      searchHistory = data;
    },
  });
  // 历史记录上限为10条
  if (searchHistory.length >= 10) searchHistory.pop();
  // 将搜索记录压入数组，并通过 Set 集合去重
  searchHistory.unshift(userInput);
  searchHistory = Array.from(new Set(searchHistory));
  // 存储到 lcoalStorage
  storage.setItem({ key: 'searchHistory', data: searchHistory });
}

interface iHandleKeyDownFun {
  handleKeyDown: (word: string) => void;
}

// 用户搜索事件
function handleKeyDownFun(
  state: { userInput: string },
  emit: (event: string, ...args: any[]) => void,
): iHandleKeyDownFun {
  // 用户回车搜索
  function handleKeyDown(word: string) {
    axios
      .get(`/search?keywords=${word}`)
      .then((res) => {
        if (res === null || res.data === undefined || res.data.code === 400) return;
        const { songs } = res.data.result;
        emit('childByValue', songs);
        emit('isSearchLoading', false);
      })
      .catch((err) => {
        console.log(`/search?keywords=${word} request error:`);
        console.info(err);
      });
    HistorayStorage(state.userInput);
  }
  return {
    handleKeyDown,
  };
}

interface iHandleToSuggestFun {
  handleToSuggest: (userInput: string) => void;
}
// 用户输入提示
function handleToSuggestFun(emit: (event: string, ...args: any[]) => void): iHandleToSuggestFun {
  function handleToSuggest(userInput: string) {
    axios
      .get(`/search/suggest?keywords=${userInput}&type=mobile`)
      .then((res) => {
        // 当请求结果为400 或者 用户清空了输入框，返回搜索页面
        if (res.data.code === 400 || userInput === '') {
          emit('searchPageType', 1);
        } else {
          // 处理数据，将数据返回父级组件,由父级组件将数据传给sugges组件
          emit('suggestResultParent', {
            searchWord: userInput,
            result: res.data.result.songs,
          });
        }
        // 处理axios beforeSendRequest 事件
        emit('isSearchLoading', false);
      })
      .catch((err) => {
        console.log(`/search/suggest?keywords=${userInput}&type=mobile request error:`);
        console.info(err);
      });
  }
  return {
    handleToSuggest,
  };
}

export default {
  name: 'music-search',
  props: ['keyword'],
  setup(props:Readonly<{keyword?:any}>,
    context: Readonly<{ emit: (event: string, ...args: any[]) => void }>) {
    const { emit } = context;
    const state = reactive({
      userInput: '',
      searchContent: '',
      suggestResult: '',
      // 用户点击 x 号返回搜索首页
      handleClickBack() {
        state.userInput = '';
        emit('searchPageType', 1);
      },
    });
    const { handleKeyDown } = handleKeyDownFun(state, emit);
    const { handleToSuggest } = handleToSuggestFun(emit);
    // 监听用户点击热搜、历史记录事件
    watch(
      // FIXME: watch 第一个参数，强制跳过了类型检查
      // @ts-ignore
      () => props.keyword,
      (keyword: string) => {
        if (keyword === '') {
          return;
        }
        state.userInput = keyword;
        handleKeyDown(keyword);
      },
    );
    return {
      ...toRefs(state),
      handleKeyDown,
      handleToSuggest,
    };
  },
};
</script>

<style scoped>
.search-input {
  display: flex;
  align-items: center;
  justify-content: center;

  height: 35px;
  margin: 20px 10px;

  color: #222;
  border-radius: 17px;
  background-color: #eee;
}

.search-input > i {
  margin: 0 10px 0 10px;

  font-size: 20px;
  font-weight: bold;
}

.search-input > input {
  width: 80%;
  height: inherit;
  margin: 0 5px;

  border: none;
  outline: none;
  background-color: transparent;

  font-size: 15px;
}
</style>
